package com.iot08.api.service;

import com.alibaba.fastjson.JSONObject;
import com.iot08.api.config.redis.RedisClusterService;
import com.iot08.api.service.supplement.KafkaService;
import com.iot08.api.vo.request.DateParamReqVO;
import com.iot08.api.vo.request.StepTankingReqVO;
import com.iot08.api.vo.request.TargetParamReqVO;
import com.iot08.common.constant.Const;
import com.iot08.common.constant.ConstCacheField;
import com.iot08.common.constant.ConstKafka;
import com.iot08.common.entity.app.Device;
import com.iot08.common.entity.app.DeviceStepDaily;
import com.iot08.common.entity.app.DeviceStepSet;
import com.iot08.common.service.base.BaseService;
import com.iot08.common.utils.DateUtil;
import com.iot08.common.utils.response.ResponseEnum;
import com.iot08.common.utils.response.ResponseMap;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @version 1.0
 * @Description:
 * @author: Rock
 * @time: 2021/1/23 16:34
 */
@Slf4j
@Service
public class DeviceStepDailyService extends BaseService<DeviceStepDaily> {

    @Resource
    private DeviceStepSetService deviceStepSetService;



    @Resource
    private KafkaService kafkaService;

    @Resource
    private RedisClusterService redisClusterService;

    /**
     * @param imei
     * @param date
     * @time: 2021/2/4 14:19
     * @author: Rock
     * @version 1.0
     */
    private DeviceStepDaily get(String imei, String date) {
        Query query = new Query(Criteria.where("i").is(imei).and("date").is(date));
        return this.findOne(query);
    }

    /**
     * 查询今日计步统计
     *
     * @param imei
     * @param vo
     * @time: 2021/2/4 14:32
     * @author: Rock
     * @version 1.0
     */
    public ResponseMap getStepDaily(String imei, DateParamReqVO vo) {
        ResponseMap res = ResponseMap.success();

        DeviceStepSet deviceStepSet = deviceStepSetService.findById(imei);
        if (deviceStepSet == null) {
            //创建一个默认的
            deviceStepSet = deviceStepSetService.create(imei, Const.DEF_TARGET_STEP);
        }
        if(vo.getStartDate() == null || vo.getDate().equals(vo.getStartDate())){
            // 当天
            Criteria criteria = Criteria.where("i").is(imei).and("date").is(vo.getDate());
            DeviceStepDaily dateDeviceStepDaily = this.findOne(new Query(criteria).with(Sort.by(Sort.Order.asc("t"))));
            JSONObject data = new JSONObject();
            if(dateDeviceStepDaily == null){
                data.put("num", 0);
                data.put("target", deviceStepSet.getTarget());
                data.put("distance", 0);
                data.put("calorie", 0);
                data.put("date", vo.getDate());
                data.put("timestamp", DateUtil.nowTimestampToLong());
            }else{
                data.put("num", dateDeviceStepDaily.getNum());
                data.put("target", dateDeviceStepDaily.getTarget());
                data.put("distance", dateDeviceStepDaily.getDistance());
                data.put("calorie", dateDeviceStepDaily.getCalorie());
                data.put("date", dateDeviceStepDaily.getDate());
                data.put("timestamp", dateDeviceStepDaily.getTime());
            }
            res.put("data", data);
        }else{
            List<String> dataDayList = new ArrayList<>();
            //查找起点
//            Date beforeQTime = DateUtil.strToDate(vo.getStartDate());

            //终点
//            Date endQTime = DateUtil.strToDate(vo.getDate());
            Criteria criteria = Criteria.where("i").is(imei).andOperator(Criteria.where("date").gte(vo.getStartDate()),
                    Criteria.where("date").lte(vo.getDate()));
            List<DeviceStepDaily> stepList = this.find(new Query(criteria).with(Sort.by(Sort.Order.asc("date"))).limit(30));

            //今天日期 和 步数
            int todaySetp = 0;
            String todayStr = DateUtil.dateToStr(new Date(), DateUtil.FORMAT_4);
            if (stepList != null && stepList.size() > 0) {
                for (DeviceStepDaily step : stepList) {
                    if (step == null) {
                        continue;
                    }
                    if (vo.getDate().equals(step.getDate())) {
                        Map<String, Object> temp = new HashMap<>();
                        temp.put("num", step.getNum() == null ? 0 : step.getNum());
                        temp.put("target", step.getTarget() == null ? Const.DEF_TARGET_STEP : step.getTarget());
                        temp.put("distance", step.getDistance() == null ? 0 : step.getDistance());
                        temp.put("calorie", step.getCalorie() == null ? 0 : step.getCalorie());
                        temp.put("date", step.getDate());
                        temp.put("timestamp", step.getTime());
                    }
                    if (!dataDayList.contains(step.getDate())) {
                        dataDayList.add(step.getDate());
                    }
                    if(step.getDate().equals(todayStr)){
                        todaySetp = step.getNum() == null ? 0 : step.getNum();
                    }
                }
            }
            res.put("todaySetp", todaySetp);
            res.put("dataList", dataDayList);
        }
        res.put("switchStatus", deviceStepSet.getSwitchStatus());
        return res;
    }

    /**
     * 设置今日目标步数
     *
     * @param imei
     * @param vo
     * @time: 2021/2/4 14:25
     * @author: Rock
     * @version 1.0
     */
    public ResponseMap addTodayTargetStep(String imei, TargetParamReqVO vo) {
        //设备不在线不进行下发
        String onlineStatus = redisClusterService.hget(imei, ConstCacheField.ONLINE_STATUS);
        if (!"1".equals(onlineStatus)) {
            return ResponseMap.fail(ResponseEnum.STATUS5001.getCode(), ResponseEnum.STATUS5001.getMsg());
        }
        DeviceStepSet deviceStepSet = deviceStepSetService.findById(imei);
        if (deviceStepSet == null) {
            //创建一个默认的
            deviceStepSet = deviceStepSetService.create(imei, Const.DEF_TARGET_STEP);
        }
        if("switch".equals(vo.getCmd()) || "switchStatus".equals(vo.getCmd())){
            //开关
            deviceStepSet.setSwitchStatus(vo.getOptions());
            deviceStepSetService.save(deviceStepSet);
            vo.setTarget(deviceStepSet.getTarget());
        } else {
            //设置目标步数
            //找出当天的计步记录
            String todayStr = DateUtil.dateToStr(new Date(), DateUtil.FORMAT_4);
            DeviceStepDaily daily = get(imei, todayStr);
            if (daily == null) {
                daily = new DeviceStepDaily();
                daily.setImei(imei);
                daily.setNum(0);
                daily.setExpiryAt(DateUtil.getSystemExpiryAt());
                daily.setDate(todayStr);
                daily.setTarget(vo.getTarget());
                daily.setTime(System.currentTimeMillis() / 1000);
                this.save(daily);
            } else {
                this.updateById(new ObjectId(daily.getId()), new Update().set("target", vo.getTarget()));
            }
            //如果是计步开关是关闭状态的那么 修改目标步数的时候 不下发指令
            if(vo.getOptions() == 0){
                return ResponseMap.success();
            }
        }
        //设置完往 TCP 发条指令
        JSONObject targetStepData = new JSONObject();
        targetStepData.put("target", vo.getTarget());
        targetStepData.put("status", vo.getOptions());
        //setSetpSwitch
        kafkaService.emitDeviceDemand(imei, ConstKafka.DEVICE_TYPE_SetSetpSwitch, targetStepData, vo.getOpenid());
        return ResponseMap.success();
    }


    /**
     * 查询日、周、月排行榜
     * @param imei
     * @param vo
     * @time: 3/12/22 5:58 PM
     * @author: Weichao
     * @version 1.0
     */
    public ResponseMap getRanking(String imei, StepTankingReqVO vo) {
        if(vo.getDay() != null){
            //某天
            String todayStr = vo.getDay();

        }else if (vo.getWeek() == 1) {
            //最近一周

        }else if (vo.getMonth() == 1) {
            //最近一年

        }
        return ResponseMap.success();
    }

}
